#include "stdafx.h"
#include "thread/atomiccounter.hpp"

namespace JHCPP
{
	namespace thread
	{
		CAtomicCounter::CAtomicCounter() : m_counter(0)
		{
		}

		CAtomicCounter::CAtomicCounter(CAtomicCounter::ValueType initialValue) : m_counter(initialValue)
		{
		}

		CAtomicCounter::CAtomicCounter(const CAtomicCounter& counter) : m_counter(counter.value())
		{
		}

		CAtomicCounter::~CAtomicCounter()
		{
		}

	#if defined(JH_OS_WINDOWS)
		CAtomicCounter& CAtomicCounter::operator = (const CAtomicCounter& counter)
		{
			InterlockedExchange(&m_counter, counter.value());
			return *this;
		}

		CAtomicCounter& CAtomicCounter::operator = (CAtomicCounter::ValueType value)
		{
			InterlockedExchange(&m_counter, value);
			return *this;
		}
		
		CAtomicCounter::ValueType CAtomicCounter::operator ++ () // prefix
		{
			return InterlockedIncrement(&m_counter);
		}

		CAtomicCounter::ValueType CAtomicCounter::operator ++ (int) // postfix
		{
			ValueType result = InterlockedIncrement(&m_counter);
			return --result;
		}

		CAtomicCounter::ValueType CAtomicCounter::operator -- () // prefix
		{
			return InterlockedDecrement(&m_counter);
		}

		CAtomicCounter::ValueType CAtomicCounter::operator -- (int) // postfix
		{
			ValueType result = InterlockedDecrement(&m_counter);
			return ++result;
		}

		bool CAtomicCounter::operator ! () const
		{
			return m_counter == 0;
		}
	#elif defined(JH_OS_LINUX)
		CAtomicCounter& CAtomicCounter::operator = (const CAtomicCounter& counter)
		{
			__sync_lock_test_and_set(&m_counter, counter.value());
			return *this;
		}

		CAtomicCounter& CAtomicCounter::operator = (CAtomicCounter::ValueType value)
		{
			__sync_lock_test_and_set(&m_counter, value);
			return *this;
		}

		CAtomicCounter::ValueType CAtomicCounter::operator ++ () // prefix
		{
			return __sync_add_and_fetch(&m_counter, 1);
		}

		CAtomicCounter::ValueType CAtomicCounter::operator ++ (int) // postfix
		{
			return __sync_fetch_and_add(&m_counter, 1);
		}

		CAtomicCounter::ValueType CAtomicCounter::operator -- () // prefix
		{
			return __sync_sub_and_fetch(&m_counter, 1);
		}

		CAtomicCounter::ValueType CAtomicCounter::operator -- (int) // postfix
		{
			return __sync_fetch_and_sub(&m_counter, 1);
		}

		bool CAtomicCounter::operator ! () const
		{
			return m_counter == 0;
		}
	#endif

		CAtomicCounter::operator CAtomicCounter::ValueType () const
		{
			return m_counter;
		}

		CAtomicCounter::ValueType CAtomicCounter::value() const
		{
			return m_counter;
		}


	}//end of namespace thread
}//end of namespace JHCPP
